﻿using System.Text.Json;
using Digitalmes.Domain;
using Digitalmes.Scada.Configuration;
using Digitalmes.Scada.Models;
using Digitalmes.Scada.Services;

namespace Digitalmes.Scada.Handlers;

/// <summary>
/// 上件请求处理器
/// </summary>
internal sealed class ReqHandler : AbstractHandler, ITransientDependency
{
    private readonly IReqService _reqService;
    private readonly ILogger _logger;

    public ReqHandler(IReqService reqService, ILogger<EntryHandler> logger)
    {
        _reqService = reqService;
        _logger = logger;
    }

    public override async Task<HandleResult> HandleAsync(RequestMessage message, CancellationToken cancellationToken = default)
    {
        var sn = message.GetString(TagDefine.PLC_Req_SN);

        // 请求日志
        _logger.LogInformation("[上线请求数据] {SN}, 工位：{OpCode}，数据：{Message}",
           sn ?? "",
           message.Schema.TagGroupName,
           JsonSerializer.Serialize(message.Values.Select(s => new { s.TagName, s.Address, s.Value })));

        if (string.IsNullOrWhiteSpace(sn))
        {
            return LogAndReturn(ErrCode.E1001, message.Schema.TagGroupName!);
        }

        var formual = message.GetString(TagDefine.PLC_Req_Formual);
        if (string.IsNullOrEmpty(formual))
        {
            return LogAndReturn(ErrCode.E1002, message.Schema.TagGroupName!);
        }

        ReqInput input = new()
        {
            LineCode = message.Schema.ChannelName,
            OpCode = message.Schema.TagGroupName,
            SN = sn,
            FormualNo = formual,
        };

        try
        {
            var result = await _reqService.ReqAsync(input);

            // 响应日志
            string logCallbackItems = result.CallbackItems != null ? JsonSerializer.Serialize(result.CallbackItems) : "[]";
            _logger.LogInformation("[上线响应数据] {SN}, 工位：{OpCode}，状态: {State}, 消息: [{InnerErrorCode}]-{ErrMessage}; 回调值: {CallbackItems}",
                sn,
                message.Schema.TagGroupName,
                result.State.ToString(),
                result.InnerErrorCode.ToString(),
                result.GetErrorMessage(),
                logCallbackItems);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[上线服务处理异常] {SN}, 工位：{OpCode}",
                sn,
                message.Schema.TagGroupName);
            return HandleResult.Error();
        }
    }

    private HandleResult LogAndReturn(ErrCode errCode, string opCode)
    {
        var result = HandleResult.Error(errCode);
        _logger.LogWarning("[上线响应数据] 工位：{OpCode}，状态: {State}, 消息: [{InnerErrorCode}]-{ErrMessage}",
                opCode,
                result.State.ToString(),
                result.InnerErrorCode.ToString(),
                result.GetErrorMessage());

        return result;
    }
}
